package edu.ustb.sei.emft.resourceUtil;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;

public class ResourceUtil {
	
	static private ResourceUtil instance = new ResourceUtil();
	
	static public ResourceUtil getDefault() {
		return instance;
	}

	public ResourceUtil() {
		resourceSet = new ResourceSetImpl();

		resourceSet
				.getResourceFactoryRegistry()
				.getExtensionToFactoryMap()
				.put(Resource.Factory.Registry.DEFAULT_EXTENSION,
						new XMIResourceFactoryImpl());
	}

	public ResourceUtil(ResourceSet resourceSet) {
		this.resourceSet = resourceSet;
	}

	protected ResourceSet resourceSet = null;

	public ResourceSet getResourceSet() {
		return resourceSet;
	}

	public Resource loadResource(String path, boolean isFilePath,
			boolean forceReloading) {
		URI uri = null;

		if (isFilePath)
			uri = URI.createFileURI(path);
		else
			uri = URI.createPlatformResourceURI(path, true);

		if (forceReloading) {
			Resource toBeRemoved = null;
			for (Resource r : resourceSet.getResources()) {
				if (r.getURI().equals(uri)) {
					toBeRemoved = r;
					break;
				}
			}

			if (toBeRemoved != null)
				resourceSet.getResources().remove(toBeRemoved);
		}

		return resourceSet.getResource(uri, true);
	}

	public Resource loadFileResource(String path) {
		return loadFileResource(path, false);
	}

	public Resource loadFileResource(String path, boolean forceReloading) {
		return loadResource(path, true, forceReloading);
	}

	public Resource loadPlatformResource(String path) {
		return loadPlatformResource(path, false);
	}

	public Resource loadPlatformResource(String path, boolean forceReloading) {
		return loadResource(path, false, forceReloading);
	}
	
	public Resource loadMetamodel(String path, boolean isFilePath) {
		Resource res = this.loadResource(path, isFilePath, false);
		
		if(res!=null) {
			for(EObject o : res.getContents()){
				EPackage pkg = (EPackage) o;
				resourceSet.getPackageRegistry().put(pkg.getNsURI(), pkg);
			}
		}
		
		return res;
	}
	
	public Resource loadMetamodelFromFile(String path) {
		return loadMetamodel(path,true);
	}
	
	public Resource loadMetamodelFromPlatform(String path) {
		return loadMetamodel(path,false);
	}
	
	public Resource createResource(String path, boolean isFilePath) {
		URI uri = null;

		if (isFilePath)
			uri = URI.createFileURI(path);
		else
			uri = URI.createPlatformResourceURI(path, true);
		
		return resourceSet.createResource(uri);
	}
	
	public Resource createFileResource(String path) {
		return createResource(path,true);
	}
	
	public Resource createPlatformResource(String path) {
		return createResource(path,false);
	}
	
	public boolean saveResource(Resource res) {
		Map<Object,Object> option = new HashMap<Object,Object>();
		option.put(XMLResource.OPTION_SCHEMA_LOCATION, true);
		try {
			res.save(option);
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	public boolean saveResource(EObject obj, Resource res) {
		res.getContents().add(obj);
		return saveResource(res);
	}
	
	public boolean saveResource(List<EObject> objs, Resource res) {
		for(EObject o : objs) {
			if(o.eContainer()==null)
				res.getContents().add(o);
		}
		return saveResource(res);
	}
}
